package distributed.controller;

import java.sql.Date;
import java.util.ArrayList;

import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import distributed.entity.Event;
import distributed.entity.EventModel;

import server.ClientState;
import xml.Message;

/**
 * Controller to handle an admin removing events
 * @author Sam Jaffe, Patrick Feeney
 *
 */
public class RemoveEventController implements IProtocolController{

	/** Processes a message from a client */
	public Message process(ClientState state, Message request) {
		String xmlString;
		//Get the request attributes
		NamedNodeMap map = request.contents.getFirstChild().getAttributes();
		Node idNode = map.getNamedItem("id"); //Get the is node
		
		String key = map.getNamedItem("key").getNodeValue(); //Get the key for validation
		int affected = 0;
		
		if (!key.equals(state.getData())) { //Make sure its valid
			xmlString = Message.responseHeader(request.id(), "Invalid Authentication Key") +
			"<removeResponse numberAffected='" + affected + "'/></response>";
			return new Message(xmlString);
		}
		
		if (idNode == null) { //If the id node isn't there
			Node compNode = map.getNamedItem("completed");
			Node daysNode = map.getNamedItem("daysOld");
			if (compNode == null && daysNode == null) { //If there's no data
				xmlString = Message.responseHeader(request.id(), "Not enough info"); //Not Enough Info
			}
			else { //We need to store the event data
				ArrayList<String> toRemove = new ArrayList<String>();
				xmlString = Message.responseHeader(request.id());
				EventModel em = EventModel.getInstance();
				
				if (daysNode != null) { //If the day node is there
					Date today = new Date(System.currentTimeMillis()-
							(Long.decode(daysNode.getNodeValue())*86400000L));
					DataBaseController dbc = DataBaseController.getInstance();
					
					for (String id : em.getEventIDs()) { //Kill all the old stuff
						Event e = em.getEvent(id);
						if (e.getCreationDate().before(today)) {
							affected++;
							toRemove.add(id);
							try { //Ensure its removed from the database
								dbc.deleteEvent(id);
							} catch (Exception e1) {}
						}
					}
					try { //Then look at the database
						for (String id : dbc.getIdsOfOldEvents(today)) {
							Event e = dbc.retrieveEvent(id);
							if (e.getCreationDate().before(today) && !toRemove.contains(id)) {
								affected++;
								dbc.deleteEvent(id);
							}
						}
					} catch (Exception e) {}
				}
				
				if (compNode != null) { // If we care about complete events
					boolean shouldClosed = Boolean.parseBoolean(compNode.getNodeValue());
					DataBaseController dbc = DataBaseController.getInstance();

					// Go through all the events
					for (String id : em.getEventIDs()) {
						Event e = em.getEvent(id); //If there closed and we haven't removed them yet
						if (shouldClosed == e.done() && !toRemove.contains(id)) {
							affected++;
							toRemove.add(id);
						}
					}
					
					try { //Get every single DB event (lolwut)
						for (String id : dbc.getIdsOfOldEvents(
								new Date(System.currentTimeMillis()+86400000L))) {
							Event e = dbc.retrieveEvent(id);
							if (shouldClosed == e.done() && !toRemove.contains(id))  { 
								//Kill the ones with the appropriate status
								affected++;
								dbc.deleteEvent(id);
							}
						}
					} catch (Exception e) {}
				}
				for (String id : toRemove) {
					em.removeEvent(id); // Remove all of the events (avoid concurrency error)
				}
				toRemove.clear();
			}
		}
		else { //Now for a given id
			Event e = EventModel.getInstance().getEvent(idNode.getNodeValue());
			if (e != null) { //Make sure it exists
				xmlString = Message.responseHeader(request.id());
				affected++; //If so, RID
				EventModel.getInstance().removeEvent(idNode.getNodeValue());
			}
			else
				xmlString = Message.responseHeader(request.id(), "This event does not exist");
		}
				
		xmlString += "<removeResponse numberAffected='" + affected + "'/></response>";
		// Let us know how much damage we did
		return new Message(xmlString);
	}

	/**
	 * @return RemoveEventController
	 */
	public IProtocolController newCopy() {
		return new RemoveEventController();
	}

}
